/*
 * OREKIT-X
 * Copyright 2002-2008 CS Communication & Systemes
 * 
 * Parts of this software package have been licensed to CS
 * Communication & Systemes (CS) under one or more contributor license
 * agreements.  See the NOTICE file distributed with this work for
 * additional information.
 *  
 * This is an experimental copy of OREKIT from www.orekit.org.
 * Please use the original OREKIT from orekit.org for normal work
 * unrelated to this research project.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You
 * may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied.  See the License for the specific language governing
 * permissions and limitations under the License.
 */
package ore.forces.drag;

import ore.Frame;
import ore.PositionVelocity;
import ore.Transform;
import ore.bodies.BodyShape;
import ore.bodies.GeodeticPoint;
import ore.errors.OrekitException;
import ore.time.AbsoluteDate;

import org.apache.commons.math.geometry.Vector3D;

/** 
 * This model represents a simple atmosphere with an exponential
 * density and rigidly bound to the underlying rotating body.
 * 
 * @author Fabien Maussion
 * @author Luc Maisonobe
 */
public class SimpleExponentialAtmosphere
    implements Atmosphere
{

    /** Earth shape model.
     */
    public final BodyShape    shape;

    /** Earth reference frame.
     */
    public final Frame        bodyFrame;

    /** Reference density.
     */
    public final double       rho0;

    /** Reference altitude.
     */
    public final double       h0;

    /** Reference altitude scale.
     */
    public final double       hscale;


    /** 
     * @param shape body shape model
     * @param bodyFrame body rotation frame
     * @param rho0 Density at the altitude h0
     * @param h0 Altitude of reference (m)
     * @param hscale Scale factor
     */
    public SimpleExponentialAtmosphere(BodyShape shape, Frame bodyFrame,
                                       double rho0, double h0, double hscale) {
        this.shape  = shape;
        this.bodyFrame = bodyFrame;
        this.rho0   = rho0;
        this.h0     = h0;
        this.hscale = hscale;
    }


    /** {@inheritDoc}
     */
    public double getDensity(AbsoluteDate date, Vector3D position, Frame frame)
        throws OrekitException
    {
        GeodeticPoint gp = this.shape.transform(position, frame, date);
        return this.rho0 * Math.exp((this.h0 - gp.getAltitude()) / hscale);
    }
    /** {@inheritDoc}
     */
    public Vector3D getVelocity(AbsoluteDate date,
                                Vector3D position, Frame frame)
        throws OrekitException
    {
        Transform bodyToFrame = this.bodyFrame.getTransformTo(frame, date);
        Vector3D posInBody = bodyToFrame.getInverse().transformPosition(position);
        PositionVelocity pvBody = new PositionVelocity(posInBody, new Vector3D(0, 0, 0));
        PositionVelocity pvFrame = bodyToFrame.transformPositionVelocity(pvBody);
        return pvFrame.getVelocity();
    }

}
